from flask import request, Blueprint
from common.log import log_handler
import requests
from config.config import *
import json
from urllib.request import urlretrieve
import zipfile
from common.utils.format_util import py_to_java, err_formatter
import os
import shutil
import subprocess
import time
log = log_handler.LogHandler().get_log()

am = Blueprint('am', __name__)


@am.route('/healthy/liveness', methods=['GET'])
def liveness():
    return "ok"


@am.route('/healthy/readiness', methods=['GET'])
def readiness():
    return "ok"


def download_from_insight(mo_id):
    url = INSIGHT_SERVER + "modelOnline/install/" + str(mo_id)

    # os.mkdir(AM_WAREHOUSE)
    target_zip_path = os.path.join(AM_WAREHOUSE, "mo_" + str(mo_id) + ".zip")
    log.info(f"url: {url} \n target_zip_path: {target_zip_path}")
    if not os.path.isfile(target_zip_path):
        urlretrieve(url, target_zip_path)

    if not os.path.isdir(os.path.join(AM_WAREHOUSE, "mo_" + str(mo_id))):
        with zipfile.ZipFile(target_zip_path, 'r') as zip_ref:
            zip_ref.extractall(AM_WAREHOUSE)


@am.route('/recStreaming', methods=['GET'])
def recStreaming():
    mo_id = request.args.get('moid')
    url = INSIGHT_SERVER + "modelOnline/install/" + str(mo_id)
    response = requests.get(url)
    string = response.read().decode('utf-8')
    json_obj = json.loads(string)
    return mo_id


@am.route('/install', methods=['GET'])
def install():
    mo_id = request.args.get('moid')
    download_from_insight(mo_id)
    return "success"


@am.route('/getSetParams', methods=['GET'])
def get_set_params():
    mo_id = request.args.get('moid')
    contents = ""
    try:
        mo_dir = os.path.join(AM_WAREHOUSE, "mo_" + str(mo_id))
        if not os.path.exists(mo_dir):
            mo_id = mo_dir.split("_")[-1]
            download_from_insight(mo_id)
        sp_json_path = os.path.join(AM_WAREHOUSE, "mo_" + str(mo_id) + "/my_model_params.json")
        with open(sp_json_path, 'r') as j:
            contents = json.loads(j.read())
    except Exception as e:
        return err_formatter(e)
    return py_to_java(str(contents))


def copytree(src, dst, symlinks=False, ignore=None):
    for item in os.listdir(src):
        s = os.path.join(src, item)
        d = os.path.join(dst, item)
        if os.path.isdir(s):
            shutil.copytree(s, d, symlinks, ignore)
        else:
            shutil.copy2(s, d)


@am.route('/loadToPipeline', methods=['POST'])
def loadToPipeline():
    try:
        params = request.form.to_dict()
        mo_dir = params.get("moDirPath")
        target = params.get("target")
        os.mkdir(target)
        if not os.path.exists(mo_dir):
            mo_id = mo_dir.split("_")[-1]
            download_from_insight(mo_id)
        copytree(mo_dir, target)

    except Exception as e:
        return err_formatter(e)
    return ""


@am.route('/copyDir', methods=['POST'])
def copyDir():
    try:
        params = request.form.to_dict()
        source = params.get("source")
        target = params.get("target")
        os.mkdir(target)
        copytree(source, target)

    except Exception as e:
        return err_formatter(e)
    return ""


@am.route('/loadData', methods=['POST'])
def load_data():
    try:
        params = request.form.to_dict()
        cmd = params.get("cmd")
        log.info(cmd)
        tmp = os.popen(cmd).readlines()
        log.info(tmp)
    except Exception as e:
        return err_formatter(e)
    return ""


@am.route('/run', methods=['POST'])
def run():
    start_time = time.time()
    log.info("start runnig")
    output = {"stdout": ""}
    try:
        params = request.form.to_dict()
        cmd = params.get("cmd")
        log.info("run" + cmd)
        p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        stdout, stderr = p.communicate()
        if len(stderr) != 0:
            output["error_msg"] = py_to_java(str(stderr))
        if len(stdout) != 0:
            output["stdout"] = py_to_java(str(stdout))
    except Exception as e:
        return err_formatter(e)
    log.info("run finished")
    log.info(output)
    log.info(f"am time: {time.time() - start_time}")
    return str(output)


@am.route('/recUpdate', methods=['POST'])
def rec_update():
    log.info("start rec")
    output = {"stdout": ""}
    try:
        params = request.form.to_dict()
        cmd = params.get("cmd")
        log.info("recupdate:" + cmd)
        p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        stdout, stderr = p.communicate()

        if len(stderr) != 0:
            output["error_msg"] = py_to_java(str(stderr))
        if len(stdout) != 0:
            output["stdout"] = py_to_java(str(stdout))
    except Exception as e:
        return err_formatter(e)
    return str(output)


@am.route('/delNode', methods=['POST'])
def del_node():
    try:
        params = request.form.to_dict()
        taskId = params.get("taskId")
        file_tbd = AM_WAREHOUSE + "ml_" + str(taskId)
        shutil.rmtree(file_tbd)
    except Exception as e:
        return err_formatter(e)
    return ""
